package com.migu.spms.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.migu.spms.common.StringUtil;
import com.migu.spms.constant.Constant;
import com.migu.spms.dao.entity.BaseLineCriteria;
import com.migu.spms.dao.entity.BaseLineDO;
import com.migu.spms.dao.entity.BasePage;
import com.migu.spms.dao.entity.ChangeHistoryCriteria;
import com.migu.spms.dao.entity.ChangeHistoryDO;
import com.migu.spms.dao.entity.FunctionRequireCriteria;
import com.migu.spms.dao.entity.FunctionRequireDO;
import com.migu.spms.dao.entity.FunctionRequirementCorrelationRequireCriteria;
import com.migu.spms.dao.entity.ProjectCriteria;
import com.migu.spms.dao.entity.ProjectDO;
import com.migu.spms.dao.entity.RequireAttachmentCriteria;
import com.migu.spms.dao.entity.RequireAttachmentDO;
import com.migu.spms.dao.entity.RequireUserCriteria;
import com.migu.spms.dao.entity.RequireUserDO;
import com.migu.spms.dao.entity.SubParentRequireCriteria;
import com.migu.spms.dao.entity.SubParentRequireDO;
import com.migu.spms.dao.inf.IBaseLineDO;
import com.migu.spms.dao.inf.IChangeHistoryDO;
import com.migu.spms.dao.inf.IFunctionRequireDO;
import com.migu.spms.dao.inf.IFunctionRequirementCorrelationRequireDO;
import com.migu.spms.dao.inf.IProjectDO;
import com.migu.spms.dao.inf.IRequireAttachmentDO;
import com.migu.spms.dao.inf.IRequireTypeTreeDO;
import com.migu.spms.dao.inf.IRequireUserDO;
import com.migu.spms.dao.inf.ISubParentRequireDO;
import com.migu.spms.service.data.FunctionRequireCompare;
import com.migu.spms.service.data.PaginationResult;
import com.migu.spms.service.data.User;
import com.migu.spms.service.inf.IBaseLineService;
import com.migu.spms.service.inf.IChangeHistoryService;
import com.migu.spms.service.inf.IFunctionFlowService;
import com.migu.spms.service.inf.ISequenceCreateService;
import com.migu.spms.utils.CodeCreateUtil;
import com.migu.spms.utils.PropertiesCopyUtil;
import com.migu.spms.utils.exception.ServiceException;
import com.migu.spms.webapi.data.EditRequireRequest;
import com.migu.spms.webapi.data.FunctionFlowRequest;
import com.migu.spms.webapi.data.RequirementResponse;

/**
 *  xl
 *
 */
@Transactional(propagation=Propagation.SUPPORTS)
@Service("baseLineServiceImpl")
public class BaseLineServiceImpl extends PublicService implements IBaseLineService{

	@Resource(name = "IBaseLineDO")
	private IBaseLineDO baseLineDO;
	
	@Resource(name = "IFunctionRequireDO")
	private IFunctionRequireDO functionRequireDO;
	
	@Resource(name = "ISubParentRequireDO")
	private ISubParentRequireDO subParentRequireDO;
	
	@Resource(name = "sequenceService")
	private ISequenceCreateService sequenceCreateService;
	
	@Resource(name = "IFunctionRequirementCorrelationRequireDO")
	private IFunctionRequirementCorrelationRequireDO functionRequirementCorrelationRequireDO;
	
	@Resource(name = "functionFlowServiceImpl")
	private IFunctionFlowService functionFlowService;
	
	@Resource(name = "IRequireAttachmentDO")
	private IRequireAttachmentDO requireAttachmentDO;
	
	@Resource(name = "IRequireUserDO")
	private IRequireUserDO requireUserDO;
	
	@Resource(name = "IRequireTypeTreeDO")
	private IRequireTypeTreeDO requireTypeTreeDO;
	
	@Resource(name = "IRequireAttachmentDO")
    private IRequireAttachmentDO fileAttachDO;
	
	@Resource(name = "changeHistoryServiceImpl")
    private IChangeHistoryService changeHistoryService;
	
	@Resource(name = "IProjectDO")
	private IProjectDO projectDO;
	
	@Resource(name = "IChangeHistoryDO")
	private IChangeHistoryDO changeHistoryDO;
	
	@SuppressWarnings("unchecked")
	@Override
	public PaginationResult getAllUnBasedLineRequirement(BaseLineCriteria criteria) {
		List<FunctionRequireDO> requires = new ArrayList<>();
		BasePage basePage =new BasePage();
		if(criteria != null){
			String baseLineVersion = criteria.getBaseLineVersion();
			Long projectId =  criteria.getProjectId();
			if(baseLineVersion != null && baseLineVersion !="" && projectId != null){
				criteria.setIsBasedLine(Constant.isBaseLine.UNBASEDLINE);
				int count = baseLineDO.getAllUnFunctionRequireCount(criteria);
				addPageQuery(criteria);
				basePage = this.setBasePage(criteria, count);
				//查询未基线的需求集合
				requires = baseLineDO.getAllUnFunctionRequire(criteria);
			}
		}
		PaginationResult result = new PaginationResult();
		
		result.setRequirementList(requires);
		result.setBasePage(basePage);
		
		return result;
	}
	
	
	private void addPageQuery(BaseLineCriteria criteria) {
		int pageNo = criteria.getPageNo();
		int pageSize = criteria.getPageSize();
		int rowStar = (pageNo - 1) * pageSize;
		int rowEnd = pageNo * pageSize - 1;
		criteria.setRowSrt(rowStar);
		criteria.setRowEnd(rowEnd);
	}

	/**打基线*/
	@Override
	public void updateBaseLineRequirement(BaseLineCriteria criteria) {
		if(criteria != null ){
			criteria.setIsBasedLine(Constant.isBaseLine.UNBASEDLINE);
			List<FunctionRequireDO> allUnFunctionRequire = baseLineDO.getAllUnFunctionRequirement(criteria);
			List<Long> list = new LinkedList<>();
			if(allUnFunctionRequire != null && allUnFunctionRequire.size() > 0 ){
				for(FunctionRequireDO baseLine :allUnFunctionRequire){
					Long requireId =  baseLine.getId();
					list.add(requireId);
				}
			}
			criteria.setRequireIdList(list);
			criteria.setIsBasedLine(Constant.isBaseLine.BASEDLINE);
			baseLineDO.updateRequirementBaseLine(criteria);
		}else{
			throw new ServiceException("传入的参数有误!");
		}
		
	}

	/**复制需求*/
	@Override
	public PaginationResult<RequirementResponse> copyRequirement(BaseLineCriteria criteria,User user) {
		if(criteria != null){
			Long id = criteria.getRequireKey();
			FunctionRequireDO requirement = functionRequireDO.selectByPrimaryKey(id);
			
			//复制需求
			//获取需求ID
			String requireId = "";
			try {
				requireId = sequenceCreateService.getRequireNumber();
			} catch (Exception e) {
				e.printStackTrace();
			}
			Long projectId = criteria.getProjectIds();
			String requireId2 = CodeCreateUtil.createRequireId(projectId, requireId);
			requirement.setRequireId(requireId2);
			FunctionRequireCriteria requireCriteria = PropertiesCopyUtil.copy(requirement, FunctionRequireCriteria.class);
			requireCriteria.setId(null);
			requireCriteria.setStatus(Constant.flowStatus.NEWING);
			requireCriteria.setProcessInstanceId("");
			requireCriteria.setTaskId("");
			requireCriteria.setFlowInfo("");
			requireCriteria.setProjectId(projectId);
			functionRequireDO.insertSelective(requireCriteria);
			
			Long copyRequireId = requireCriteria.getId();
			

			//建立子父需求的关联关系
			SubParentRequireCriteria sprc = new SubParentRequireCriteria();
			sprc.setSubRequireId(requirement.getId());
			List<SubParentRequireDO> selectByCriteria = subParentRequireDO.selectByCriteria(sprc);
			if(selectByCriteria != null && selectByCriteria.size() > 0){
				for(SubParentRequireDO subParent : selectByCriteria){
					if(subParent.getParentRequireId() != null){
						SubParentRequireCriteria sprcTemp = new SubParentRequireCriteria();
						sprcTemp.setSubRequireId(copyRequireId);
						sprcTemp.setParentRequireId(subParent.getParentRequireId());
						subParentRequireDO.insert(sprcTemp);
					}
				}
			}
			//建立复制需求和被复制需求的关联关系
			FunctionRequirementCorrelationRequireCriteria frcrc = new FunctionRequirementCorrelationRequireCriteria();
			frcrc.setFunctionRequireId(id.toString());
			frcrc.setCorrelationRequireId(copyRequireId.toString());
			frcrc.setIdentifi("0");
			functionRequirementCorrelationRequireDO.insert(frcrc);
			
			//复制附件
			RequireAttachmentCriteria rac = new RequireAttachmentCriteria();
			rac.setFunctionRequireId(id);
			List<RequireAttachmentDO> radoList = requireAttachmentDO.selectByCriteria(rac);
			if(radoList !=null && radoList.size() >0){
				for(RequireAttachmentDO rado :radoList){
					RequireAttachmentCriteria requireAttachment = PropertiesCopyUtil.copy(rado, RequireAttachmentCriteria.class);
					requireAttachment.setId(null);
					requireAttachment.setFunctionRequireId(copyRequireId);
					requireAttachmentDO.insert(requireAttachment);
				}
			}
			
			//复制开发人员及测试人员
			RequireUserCriteria ruc = new RequireUserCriteria();
			ruc.setFunctionRequireId(id);
			List<RequireUserDO> rudoList = requireUserDO.selectByCriteria(ruc);
			if(rudoList !=null && rudoList.size() >0){
				for(RequireUserDO rudo : rudoList){
					RequireUserCriteria ru = PropertiesCopyUtil.copy(rudo, RequireUserCriteria.class);
					ru.setId(null);
					ru.setFunctionRequireId(copyRequireId);
					requireUserDO.insert(ru);
				}
			}
			
			BaseLineCriteria criteria2 = new BaseLineCriteria();
			criteria2.setRequireKey(copyRequireId);
			//复制需求，启动新流程
			functionFlowService.startProcessFlow(criteria2.getRequireKey(), user);
			return this.getRequirement(criteria2);
		}
		return null;
	}

	/**根据需求的主键ID获取该记录的表单回显信息*/
	@Override
	public PaginationResult<RequirementResponse> getRequirement(BaseLineCriteria criteria) {
		PaginationResult<RequirementResponse> result =  new PaginationResult<RequirementResponse>();
		if(criteria != null){
			Long id = criteria.getRequireKey();
			
			RequirementResponse requirement = new RequirementResponse();
			FunctionRequireDO frdo = functionRequireDO.selectByPrimaryKey(id);
			Long projectId=frdo.getProjectId();
			String projectName=projectDO.selectProjectNameById(projectId.toString());
			requirement.setProjectName(projectName);
			RequireAttachmentCriteria requireAttachmentCriteria = new RequireAttachmentCriteria();
			requireAttachmentCriteria.setFunctionRequireId(id);
			List<RequireAttachmentDO> radoList = requireAttachmentDO.selectByCriteria(requireAttachmentCriteria);
			List<RequireAttachmentCriteria> racList = new LinkedList<>();
			if(radoList != null && radoList.size() >0){
				for(RequireAttachmentDO rado : radoList){
					RequireAttachmentCriteria rac = PropertiesCopyUtil.copy(rado, RequireAttachmentCriteria.class);
					racList.add(rac);
				}
			}
			
			RequireUserCriteria requireUserCriteria = new RequireUserCriteria();
			requireUserCriteria.setFunctionRequireId(id);
			List<RequireUserDO> rudoList = requireUserDO.selectByCriteria(requireUserCriteria);
			List<com.migu.spms.webapi.data.User> developers = new ArrayList<>();
			List<com.migu.spms.webapi.data.User> testers = new ArrayList<>();
			if(rudoList !=null && rudoList.size() > 0){
				for(RequireUserDO rudo : rudoList){
					if(rudo.getRoleId() == Constant.Role.DEVELOPER){
						com.migu.spms.webapi.data.User user = new com.migu.spms.webapi.data.User();
						user.setUserId(rudo.getUserId());
						user.setUserName(rudo.getUserName());
						developers.add(user);
					}
					if(rudo.getRoleId() == Constant.Role.TESTER){
						com.migu.spms.webapi.data.User user = new com.migu.spms.webapi.data.User();
						user.setUserId(rudo.getUserId());
						user.setUserName(rudo.getUserName());
						testers.add(user);
					}
				}
			}
			
			
//			requirement.setId(id);
//			requirement.setRequireName(frdo.getRequireName());
//			requirement.setDetails(frdo.getDetails());
//			requirement.setBaselineVersion(frdo.getBaselineVersion());
//			requirement.setRequireTypeId(frdo.getRequireTypeId());
			requirement = PropertiesCopyUtil.copy(frdo, RequirementResponse.class);
			requirement.setProjectName(projectName);
			requirement.setRequireAttachmentList(racList);;
			requirement.setDevelopers(developers);
			requirement.setTesters(testers);
			result.setRequirement(requirement);
			return result;
		}
		return null;
	}
	
	/**编辑修改需求
	 * @throws Exception */
	@Override
	public void updateRequirement(EditRequireRequest editRequireRequest,User user) throws Exception {
		if(editRequireRequest != null){
			
//			int[] changeList = editRequireRequest.initTime();//==========================处理"时间清空"，历史记录会记录“1970”的问题
			
			FunctionRequireCriteria frc = PropertiesCopyUtil.copy(editRequireRequest, FunctionRequireCriteria.class);
			Long id =  frc.getId();
			FunctionRequireDO requirement = functionRequireDO.selectByPrimaryKey(id);
			
			
			 //编辑后记录
            FunctionRequireCompare compareNew = PropertiesCopyUtil.copy(editRequireRequest, FunctionRequireCompare.class);
            if(null != editRequireRequest.getDevelopers() && editRequireRequest.getDevelopers().size() > 0){
                String userNames = "";
                for (com.migu.spms.webapi.data.User us : editRequireRequest.getDevelopers()) {
                    userNames += us.getUserName()+",";
                }
                compareNew.setDeveloperStr(userNames.substring(0, userNames.lastIndexOf(",")));
            }
            if(null != editRequireRequest.getTesters() && editRequireRequest.getTesters().size() > 0){
                String userNames = "";
                for (com.migu.spms.webapi.data.User us : editRequireRequest.getTesters()) {
                    userNames +=us.getUserName()+",";
                }
                compareNew.setTesterStr(userNames.substring(0, userNames.lastIndexOf(",")));
            }
            if(null != editRequireRequest.getAttachments() && editRequireRequest.getAttachments().size() > 0){
                String userNames = "";
                for (RequireAttachmentCriteria att : editRequireRequest.getAttachments()) {
                    userNames += att.getAttachmentName()+",";
                }
                compareNew.setAttachmentStr(userNames.substring(0, userNames.lastIndexOf(",")));
            }
            
            
            //编辑前记录
            FunctionRequireCompare compareOld = PropertiesCopyUtil.copy(requirement, FunctionRequireCompare.class);
            //附件
            RequireAttachmentCriteria reAttch = new RequireAttachmentCriteria();
            reAttch.setFunctionRequireId(requirement.getId());
            List<RequireAttachmentDO> attchList = fileAttachDO.selectRequireAttachment(reAttch);
            if(null != attchList && attchList.size() > 0){
                String userNames = "";
                for (RequireAttachmentDO requireAttachmentDO : attchList) {
                    userNames += requireAttachmentDO.getAttachmentName()+",";
                    compareOld.setAttachmentStr(userNames.substring(0, userNames.lastIndexOf(",")));
                }
            }
            //开发人员
            RequireUserCriteria requireUserCriteria = new RequireUserCriteria();
            requireUserCriteria.setFunctionRequireId(requirement.getId());
            requireUserCriteria.setRoleId(Constant.Role.DEVELOPER);
            List<RequireUserDO> developers = requireUserDO.selectByCriteria(requireUserCriteria);
            if(null != developers && developers.size() > 0){
                String userNames = "";
                for (RequireUserDO requireUserDO : developers) {
                    userNames += requireUserDO.getUserName()+",";
                    compareOld.setDeveloperStr(userNames.substring(0, userNames.lastIndexOf(",")));
                }
            }
            //测试人员
            requireUserCriteria.setRoleId(Constant.Role.TESTER);
            List<RequireUserDO> testers = requireUserDO.selectByCriteria(requireUserCriteria);
            if(null != testers && testers.size() > 0){
                String userNames = "";
                for (RequireUserDO requireUserDO : testers) {
                    userNames += requireUserDO.getUserName()+",";
                    compareOld.setTesterStr(userNames.substring(0, userNames.lastIndexOf(",")));
                }
            }
            
//            //编辑关联需求(修改 or 新增 or 删除)
//            String relativeId = editRequireRequest.getRelativeBusinessRequireId();
//        	FunctionRequirementCorrelationRequireCriteria record = new FunctionRequirementCorrelationRequireCriteria();
//            record.setId(null);
//            record.setFunctionRequireId(id.toString());
//            record.setIdentifi("1");
//            List<FunctionRequirementCorrelationRequireDO> frcrDoList = functionRequirementCorrelationRequireDO.selectByCriteria(record);
//            if(frcrDoList != null && frcrDoList.size()>0){
//            	
//        		for(FunctionRequirementCorrelationRequireDO frcrDo : frcrDoList){
//            		Long frcrId = frcrDo.getId();
//            		record.setId(frcrId);
//            		record.setCorrelationRequireId(editRequireRequest.getRelativeBusinessRequireId());
//            		if(relativeId != null && !relativeId.equals("")){
//            			functionRequirementCorrelationRequireDO.updateByPrimaryKey(record);
//            		}else{
//            			functionRequirementCorrelationRequireDO.deleteByPrimaryKey(frcrId);
//            		}
//            	}
//            	
//            	
//            }else{
//            	record.setCorrelationRequireId(editRequireRequest.getRelativeBusinessRequireId());
//            	functionRequirementCorrelationRequireDO.insert(record);
//            }
            
//            editRequireRequest.resetTime(changeList);//==========================处理"时间清空"，历史记录会记录“1970”的问题
            
            if(requirement.getStatus().equals(Constant.flowStatus.NEWING)){
            	frc.setCurrentHandlerId(editRequireRequest.getDevelopResponsibleId());
            	frc.setCurrentHandlerName(editRequireRequest.getDevelopResponsibleName());
            }else if(requirement.getStatus().equals(Constant.flowStatus.TRANFER_TEST)){
            	frc.setCurrentHandlerId(editRequireRequest.getTestResponsibleId());
            	frc.setCurrentHandlerName(editRequireRequest.getTestResponsibleName());
            }
            
            String baseline = requirement.getBaselineVersion();
			String baselineVersion = editRequireRequest.getBaselineVersion();
			if(StringUtil.isEmpty(baseline) && !StringUtil.isEmpty(baselineVersion)){
				ChangeHistoryCriteria criteria = new ChangeHistoryCriteria();
				criteria.setFunctionRequireId(id);
				List<ChangeHistoryDO> selectChangeList = changeHistoryDO.selectChangeList(criteria);
				if(selectChangeList != null && selectChangeList.size() > 0){
					for (ChangeHistoryDO changeHistory : selectChangeList) {
						String operateType = changeHistory.getOperateType();
						if(!StringUtil.isEmpty(operateType) && operateType.equals(Constant.flowOperate.CREATE_NEW_REQUIREMENT)){
							if(StringUtil.isEmpty(changeHistory.getBaselineVersion())){
								criteria.setId(changeHistory.getId());
								criteria.setBaselineVersion(baselineVersion);
								changeHistoryDO.updateByPrimaryKeySelective(criteria);
							}
						}
					}
				}
			}
            
            
            functionRequireDO.updateByPrimaryKeySelective(frc);
            this.editUsersAndAttachment(editRequireRequest, id);
            
            //编辑需求，重新进入编辑之前的流程状态
        	FunctionFlowRequest flowRequest = new FunctionFlowRequest();
        	flowRequest.setOperate(Constant.flowOperate.EDIT);
        	flowRequest.setPrimaryKey(id);
        	functionFlowService.operateFlow(flowRequest, user);
            
            ChangeHistoryCriteria history = new ChangeHistoryCriteria();
            
            history.setCreateId(Long.valueOf(user.getUserId()));
            history.setCreateName(user.getUserName());
            history.setCreateTime(new Date());
            history.setIsDetails("0");
            history.setIsPermit("0");
            history.setIsBaseLine(Integer.toString(requirement.getIsBaseLine()));
            history.setFunctionRequireId(requirement.getId());
            history.setBaselineVersion(frc.getBaselineVersion());
            changeHistoryService.inesertChangeHistoryCommon(history, compareOld, compareNew);
		}
	}
	


	private void editUsersAndAttachment(EditRequireRequest editRequireRequest, Long id) {
		//根据需求 ID 删除数据库中的开发人员及测试人员
		RequireUserCriteria requireUserCriteria = new RequireUserCriteria();
		requireUserCriteria.setFunctionRequireId(id);
		List<RequireUserDO> rudoList = requireUserDO.selectByCriteria(requireUserCriteria);
		if(rudoList != null && rudoList.size() > 0){
			baseLineDO.deleteUserByCriteria(requireUserCriteria);
		}
		
		//未数据库添加开发人员
		List<com.migu.spms.webapi.data.User> developers = editRequireRequest.getDevelopers();
		if(developers != null && developers.size() > 0){
			for(com.migu.spms.webapi.data.User user : developers){
				RequireUserCriteria userCriteria = new RequireUserCriteria();
				userCriteria.setFunctionRequireId(id);
				userCriteria.setRoleId(Constant.Role.DEVELOPER);
				userCriteria.setUserId(user.getUserId());
				userCriteria.setUserName(user.getUserName());
				requireUserDO.insert(userCriteria);
			}
		}
		//为数据库添加测试人员
		List<com.migu.spms.webapi.data.User> testers = editRequireRequest.getTesters();
		if(testers != null && testers.size() > 0){
			for(com.migu.spms.webapi.data.User user : testers){
				RequireUserCriteria userCriteria = new RequireUserCriteria();
				userCriteria.setFunctionRequireId(id);
				userCriteria.setRoleId(Constant.Role.TESTER);
				userCriteria.setUserId(user.getUserId());
				userCriteria.setUserName(user.getUserName());
				requireUserDO.insert(userCriteria);
			}
		}
		
		//删除数据库中的附件信息
		RequireAttachmentCriteria rac =new RequireAttachmentCriteria();
		rac.setFunctionRequireId(id);
		List<RequireAttachmentDO> selectByCriteria = requireAttachmentDO.selectByCriteria(rac);
		if(selectByCriteria != null && selectByCriteria.size() >0){
			baseLineDO.deleteAttachmentByCriteria(rac);
		}
		
		//为数据库中添加附件
		List<RequireAttachmentCriteria> attachments = editRequireRequest.getAttachments();
		if(attachments != null && attachments.size()>0){
			for(RequireAttachmentCriteria requireAC : attachments){
				requireAC.setId(null);
				requireAC.setFunctionRequireId(id);
				requireAttachmentDO.insertSelective(requireAC);
			}
		}
	}
	
	/**项目列表*/
	@Override
	public PaginationResult<ProjectDO> getAllProject(ProjectCriteria record) {
		
		PaginationResult<ProjectDO> result = new PaginationResult<>();
		List<ProjectDO> selectByCriteria = projectDO.selectByCriteria(record);
		result.setProjectList(selectByCriteria);
		return result;
	}


	/**查询未基线的版本列表*/
	@Override
	public PaginationResult<BaseLineDO> getAllUnBasedLineVersion(BaseLineCriteria criteria) {
		if(criteria != null){
			//根据项目组id和未打基线标识查询所有未基线的版本集合
			BaseLineCriteria baseLineCriteria = new BaseLineCriteria();
			baseLineCriteria.setIsBasedLine(Constant.isBaseLine.UNBASEDLINE);
			baseLineCriteria.setProjectId(criteria.getProjectId());
			baseLineCriteria.setKeyword(criteria.getKeyword());
			List<BaseLineDO> baseLineListTemp = baseLineDO.getAllUnBasedLine(baseLineCriteria);
			List<BaseLineDO> baseLineList = new LinkedList<>();
			for(BaseLineDO bldo : baseLineListTemp){
				if(bldo.getVersion_num() != null && !bldo.getVersion_num().equals("")){
					baseLineList.add(bldo);
				}
			}
			PaginationResult<BaseLineDO> result =  new PaginationResult<>();
			result.setBaseLineList(baseLineList);
			return result;
		}
		return null;
	}
}
